//
//  ChectAppComplete.m
//  ACE
//
//  Created by ylj on 2020/2/27.
//

#import "ChectAppComplete.h"
#import <sys/stat.h>
#import <sys/sysctl.h>
#import "YLJTools.h"

@implementation ChectAppComplete

+ (BOOL)isJailBreak
{
    if ([self isSimulator]) return NO;
    
    BOOL pb = NO;
   
    // 常见越狱文件
    NSArray *pathArray = @[@"/Applications/Cydia.app",
                           @"/Library/MobileSubstrate/MobileSubstrate.dylib",
                           @"/bin/bash",
                           @"/usr/sbin/sshd",
                           @"/etc/apt"];
    
    
    for (int i = 0; i < pathArray.count; i++) {
        NSString *path = pathArray[i];
        if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
            pb = YES;
        }
    }
    
    
    // 读取系统所有的应用名称
    if ([[NSFileManager defaultManager] fileExistsAtPath:@"/User/Applications/"]) {
        pb = YES;
    }

    
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"cydia://"]]) {
        pb = YES;
    }

    
    struct stat stat_info;
    //使用stat系列函数检测Cydia等工具
    if (0 == stat("/Applications/Cydia.app", &stat_info)) {
        pb = YES;
    }
    
    
    // 读取环境变量
    char *checkInsertLib = getenv("DYLD_INSERT_LIBRARIES");
    if (checkInsertLib) {
        pb = YES;
    }
    
    return pb;
}

+ (BOOL)isSimulator {

#if TARGET_OS_SIMULATOR
    return YES;
#else
    return NO;
#endif
}


+ (BOOL)checkMachO
{
    NSBundle *bundle = [NSBundle mainBundle];
    NSDictionary *info = [bundle infoDictionary];
    if ([info objectForKey: @"SignerIdentity"] != nil){
        //存在这个key，则说明被二次打包了
        return YES;
    }
    return NO;
}

/**
 * Check if the deBUGger is attached
 *
 * Taken from https://github.com/plausiblelabs/plcrashreporter/blob/2dd862ce049e6f43feb355308dfc710f3af54c4d/Source/Crash%20Demo/main.m#L96
 *
 * @return `YES` if the deBUGger is attached to the current process,`NO` otherwise
 */
+ (BOOL)isDeBUGgerAttached
{
  static BOOL deBUGgerIsAttached = NO;
 
  static dispatch_once_t deBUGgerPredicate;
  dispatch_once(&deBUGgerPredicate,^{
    struct kinfo_proc info;
    size_t info_size = sizeof(info);
    int name[4];
 
    name[0] = CTL_KERN;
    name[1] = KERN_PROC;
    name[2] = KERN_PROC_PID;
    name[3] = getpid(); // from unistd.h,included by Foundation
 
    if (sysctl(name,4,&info,&info_size,NULL,0) == -1) {
      //NSLog(@"[HockeySDK] ERROR: Checking for a running deBUGger via sysctl() Failed: %s",strerror(errno));
      deBUGgerIsAttached = false;
    }
 
    if (!deBUGgerIsAttached && (info.kp_proc.p_flag & P_TRACED) != 0)
      deBUGgerIsAttached = true;
  });
    
  return deBUGgerIsAttached;
    
}

+ (BOOL)checkCodeSignWithProvisionID:(NSString *)jxprovisionID
{
    // 描述文件路径
    NSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"];
    if ([[NSFileManager defaultManager] fileExistsAtPath:embeddedPath]) {
        // 读取application-identifier
        NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSASCIIStringEncoding error:nil];
        NSArray *embeddedProvisioningLines = [embeddedProvisioning componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
        
        for (int i = 0; i < [embeddedProvisioningLines count]; i++) {
            if ([[embeddedProvisioningLines objectAtIndex:i] rangeOfString:@"application-identifier"].location != NSNotFound) {
                
                NSInteger fromPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"<string>"].location+8;
                
                NSInteger toPosition = [[embeddedProvisioningLines objectAtIndex:i+1] rangeOfString:@"</string>"].location;
                
                NSRange range;
                range.location = fromPosition;
                range.length = toPosition - fromPosition;
                
                NSString *fullIdentifier = [[embeddedProvisioningLines objectAtIndex:i+1] substringWithRange:range];
                
                //NSLog(@"重签名检测---%@", fullIdentifier);
                
                NSArray *identifierComponents = [fullIdentifier componentsSeparatedByString:@"."];
                NSString *appIdentifier = [identifierComponents firstObject];
               
                NSString * hashString = [YLJTools md5Str:appIdentifier];
                // 对比签名ID
                if ([hashString isEqualToString:jxprovisionID])
                {
                    return NO;
                }
                else
                {
                    return YES;
                }
            }
        }
    }
    return YES;
}

+ (BOOL)isKeyResourcesHash:(NSString *)hashValue {
    
    //type 1 比较方式
    NSArray *hashAry = [NSArray array];
    hashAry = [self getBundleFileHash];
    NSArray *sortAry = [self jxbHashSort: hashAry]; //排序
    NSString *hashTemp;
    for (NSString * fileName in sortAry) {
        if (hashTemp) {
            hashTemp = [NSString stringWithFormat:@"%@%@%@", hashTemp, @"$", fileName];
        }else {
            hashTemp = fileName;
        }
    }
//    NSLog(@"hash--- %@", hashTemp);
    
    if ([hashTemp isEqualToString:hashValue]) {
        return NO;
    }else{
        return YES;
    }
    
    
    //type 2 比较方式
//    NSArray *hashAry = [NSArray array];
//    hashAry = [self getBundleFileHash];
//    NSString *hashTemp;
////    for (NSString * fileName in hashAry) {
////        if (hashTemp) {
////            hashTemp = [NSString stringWithFormat:@"%@%@%@", hashTemp, @"$", fileName];
////        }else {
////            hashTemp = fileName;
////        }
////    }
////    NSLog(@"hash--- %@", hashTemp);
//    BOOL tempBool = false;
//    for (NSString *text in hashAry) {
//        if ([hashValue containsString:text]) {
//            tempBool = NO;
//        }else {
//            tempBool = YES;
//            return YES;
//        }
//    }
//    return tempBool;
}

//生成资源文件名及对应的hash的数组
+ (NSArray *)getBundleFileHash {
    NSMutableArray *aryHash = [NSMutableArray arrayWithCapacity:9];
    NSDictionary * fileDic = [self allFilesAtPath:[[NSBundle mainBundle] resourcePath]];
    
    for (NSString * fileName in fileDic) {
        //处理字典的键值
        NSString *fileValue = fileDic[fileName];
        //对应的文件生成哈希值
        NSString * hashText = [YLJTools md5Str: fileValue];
        if (hashText != nil) {
            [aryHash addObject:hashText];
        }
    }
 
    //所有资源文件的hash就保存在这数组里
    return aryHash;
}

//获得所有资源文件
+ (NSDictionary *)allFilesAtPath:(NSString *)dirString {
    
    NSMutableDictionary * dicHash = [NSMutableDictionary dictionary];
    NSFileManager * manager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *temp = [manager contentsOfDirectoryAtPath:dirString error:&error];
    for (NSString * fileName in temp) {
        if ([fileName containsString:@".png"] || [fileName containsString:@".jpg"] || [fileName containsString:@".gif"]) {//图片文件
            NSString * fullpath = [dirString stringByAppendingPathComponent:fileName];//路径
            NSData *fileData = [NSData dataWithContentsOfFile:fullpath];
            NSString *imgBase64Str = [fileData base64EncodedStringWithOptions:0];
            [dicHash setObject:imgBase64Str forKey:fileName];
        }else { //其它文件
            BOOL flag = YES;
            NSString * fullpath = [dirString stringByAppendingPathComponent:fileName];
            if ([manager fileExistsAtPath:fullpath isDirectory:&flag]) {
                if (!flag ) {
                    [dicHash setObject:fileName forKey:fileName];
                }
            }
        }
    }
    
    return dicHash;
}

+ (NSArray *)jxbHashSort:(NSArray *)testArray {
    
    NSArray *sortedArray = [testArray sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
        NSInteger firstInteger = 0;
        BOOL isInteger1 = [[NSScanner scannerWithString:obj1] scanInteger:&firstInteger];
        
        NSInteger secondInteger = 0;
        BOOL isInteger2 = [[NSScanner scannerWithString:obj2] scanInteger:&secondInteger];

        if (isInteger1 && isInteger2)
        {
            if (firstInteger > secondInteger) {
                return NSOrderedDescending;
            }
            else if (secondInteger > firstInteger) {
                return NSOrderedAscending;
            }
            else {
                return NSOrderedSame;
            }
        }
        else if (isInteger1) {
            return NSOrderedDescending;
        }
        else if (isInteger2) {
            return NSOrderedAscending;
        }
        else {
            return [obj1 compare:obj2 options:NSCaseInsensitiveSearch];
        }
    }];
    return sortedArray;
}

@end
